package com.zyz.forum.service.impl;

import com.zyz.forum.common.AppResult;
import com.zyz.forum.common.ResultCode;
import com.zyz.forum.dao.UserMapper;
import com.zyz.forum.exception.ApplicationException;
import com.zyz.forum.file.OSSService;
import com.zyz.forum.model.User;
import com.zyz.forum.service.IFileService;
import com.zyz.forum.service.IUserService;
import com.zyz.forum.utils.Md5Util;
import com.zyz.forum.utils.StringUtil;
import com.zyz.forum.utils.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.Date;

@Slf4j
@Service
public class UserServiceImpl implements IUserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private OSSService ossService;

    @Resource
    private IFileService fileService;

    @Value("${file.oss.downloadUrl}")
    private String downloadUrl;

    @Override
    public void createNormalUser(User user)  {
        // 1.参数校验
        if (user == null || StringUtil.isEmpty(user.getUsername())
        || StringUtil.isEmpty(user.getPassword())
        || StringUtil.isEmpty(user.getNickname())
        || StringUtil.isEmpty(user.getSalt())) {
            // 打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            // 抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 2. 按照用户名查询用户信息
        User existsUser = userMapper.selectByUserName(user.getUsername());
        // 2.1 判断是否存在,如果不存在则插入
        if (existsUser != null) {
            // 用户存在
            log.warn(ResultCode.FAILED_USER_EXISTS.toString());
            // 抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_EXISTS));
        }
        // 3. 设置默认值，插入用户
        user.setIsAdmin((byte) 0);
        user.setAvatarUrl(null);
        user.setArticleCount(0);
        user.setState((byte) 0);
        user.setDeleteState((byte) 0);
        Date data = new Date();
        user.setCreateTime(data);
        user.setUpdateTime(data);
        int row = userMapper.insertSelective(user);
        // 插入失败
        if (row != 1) {
            // 打印日志
            log.warn(ResultCode.FAILED_CREATE.toString());
            // 抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));
        }
        // 新增成功
        log.info("新增用户成功 username = " + user.getUsername() + ". ");
    }

    @Override
    public User selectByUserName(String username) {
        // 参数校验
        if (StringUtil.isEmpty(username)) {
            // 打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            // 抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 查询用户信息
        return userMapper.selectByUserName(username);
    }

    @Override
    public User login(String username, String password) {
        // 1.参数校验
        if (StringUtil.isEmpty(username) || StringUtil.isEmpty(password)) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 2.根据用户名查询用户信息
        User user = selectByUserName(username);
        // 3.user不存在
        if (user == null) {
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));
        }
        // 4.判断用户密码和数据库密码是否相同
        // 4.1 密码和盐值加密
        String encryptStr = Md5Util.md5Salt(password, user.getSalt());
        // 4.2 判断加密后的密码是否相同
        if (!encryptStr.equals(user.getPassword())) {
            log.warn(ResultCode.FAILED_LOGIN.toString()+"username : " + username);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN));
        }
        log.info("登陆成功, username = " + username);
        // 登陆成功
        return user;
    }

    @Override
    public User selectById(Long id) {
        // 参数校验
        if (id == null) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 调用mapper层
        return userMapper.selectByPrimaryKey(id);
    }

    @Override
    public void updateUserArticleCountAddOne(Long id) {
        if (id == null || id <= 0) {
            // 打印日志
            log.warn(ResultCode.FAILED_USER_ARTICLE_COUNT.toString());
            // 抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_ARTICLE_COUNT));
        }
        // 查询当前user的贴子数
        User user = userMapper.selectByPrimaryKey(id);
        if (user == null) {
            log.warn(ResultCode.ERROR_IS_NULL.toString() + " 未查询到user用户 userId = " + id);
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));
        }
        // 更新当前user的贴子数
        User updateUser = new User();
        updateUser.setId(id);
        updateUser.setArticleCount(user.getArticleCount() + 1);
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        // 判断更新是否完成
        if (row != 1) {
            log.error(ResultCode.ERROR_SERVICES.toString() + "user更新帖子数据库异常，更新失败");
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
    }

    @Override
    public void subOneArticleById(Long id) {
        // 参数校验
        if (id == null || id <= 0) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 查询当前板块信息
        User user = userMapper.selectByPrimaryKey(id);
        if (user == null) {
            // 用户不存在
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));
        }
        // 构造修改对象
        User updateUser = new User();
        updateUser.setId(id);
        updateUser.setArticleCount(user.getArticleCount() - 1);
        // 判断是否小于0
        if (updateUser.getArticleCount() < 0) {
            updateUser.setArticleCount(0);
        }
        updateUser.setUpdateTime(new Date());
        // 调用dao层
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        if (row != 1) {
            log.warn(ResultCode.ERROR_SERVICES.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
        // 修改成功
    }

    @Override
    public void updateUserInfo(User user) {
        // 判断user是否存在
        if (user == null || user.getId() == null || user.getId() <= 0) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 根据userId查询user用户是否存在
        User exitsUser = userMapper.selectByPrimaryKey(user.getId());
        if (exitsUser == null || exitsUser.getDeleteState() == 1) {
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));
        }
        // 判断用户是否被禁言
        if (exitsUser.getState() == 1) {
            log.warn(ResultCode.FAILED_USER_BANNED.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_BANNED));
        }
        // 用户存在，可以进行修改
        // 定义修改标志位
        boolean checkAttr = false;
        User updateUser = new User();
        // 设置userId
        updateUser.setId(user.getId());
        // 修改用户名
        if (!StringUtil.isEmpty(user.getUsername()) &&
                !user.getUsername().equals(exitsUser.getUsername())) {
            // 判断用户名是否相同，如果相同则不能修改
            User selectByUserName = userMapper.selectByUserName(user.getUsername());
            if (selectByUserName != null) {
                // 用户名相同用户存在，不能修改
                log.warn(ResultCode.FAILED_USERNAME_EXISTS.toString());
                throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USERNAME_EXISTS));
            }
            // 用户名不存在进行更新
            updateUser.setUsername(user.getUsername());
            // 更新标志位
            checkAttr = true;
        }
        // 更改昵称
        if (!StringUtil.isEmpty(user.getNickname()) &&
        !user.getNickname().equals(exitsUser.getNickname())) {
            // 设置昵称
            updateUser.setNickname(user.getNickname());
            // 更新标志位
            checkAttr = true;
        }
        // 更改性别
        if (user.getGender() != null &&
        !user.getGender().equals(exitsUser.getGender())) {
            // 设置性别
            updateUser.setGender(user.getGender());
            if (updateUser.getGender() > 2 || updateUser.getGender() < 0) {
                updateUser.setGender((byte) 2);
            }
            checkAttr = true;
        }
        // 更改邮箱
        if (!StringUtil.isEmpty(user.getEmail()) &&
        !user.getEmail().equals(exitsUser.getEmail())) {
            // 设置邮箱
            updateUser.setEmail(user.getEmail());
            checkAttr = true;
        }
        // 更改电话号码
        if (!StringUtil.isEmpty(user.getPhoneNum()) &&
        !user.getPhoneNum().equals(exitsUser.getPhoneNum())) {
            // 设置电话
            updateUser.setPhoneNum(user.getPhoneNum());
            checkAttr = true;
        }
        // 更改个人简介
        if (!StringUtil.isEmpty(user.getRemark()) &&
        !user.getRemark().equals(exitsUser.getRemark())) {
            updateUser.setRemark(user.getRemark());
            checkAttr = true;
        }
//        // 更改密码
//        if (StringUtil.isEmpty(user.getPassword()) &&
//        !user.getPassword().equals(exitsUser.getPassword())) {
//            // 重新生成盐值
//            String newSalt = UUIDUtil.UUID_32();
//            // 对密码进行加密
//            String md5SaltPassword = Md5Util.md5Salt(user.getPassword(), newSalt);
//            // 设置更改密码
//            updateUser.setPassword(md5SaltPassword);
//            // 设置盐值
//            updateUser.setSalt(newSalt);
//            checkAttr = true;
//        }
        // 判断更改标志位是否是true，如果是调用update
        if (checkAttr) {
            int row = userMapper.updateByPrimaryKeySelective(updateUser);
            if (row != 1) {
                log.warn(ResultCode.ERROR_SERVICES.toString());
                throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
            }
        } else {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
    }

    @Override
    public void modifyPassword(Long id, String oldPassword, String newPassword) {
        // 参数校验
        if (id == null || id <= 0 || StringUtil.isEmpty(oldPassword) || StringUtil.isEmpty(newPassword)) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 根据用户id查询用户信息
        User user = userMapper.selectByPrimaryKey(id);
        if (user == null || user.getDeleteState() == 1) {
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));
        }
        if (user.getState() == 1) {
            log.warn(ResultCode.FAILED_USER_BANNED.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_BANNED));
        }
        // 判断数据库密码和输入的老密码是否相同
        if (!user.getPassword().equals(Md5Util.md5Salt(oldPassword,user.getSalt()))) {
            // 老密码不同
            log.warn("原密码不正确！");
            throw new ApplicationException("原密码不正确！");
        }
        // 判断新密码和原密码是否相同，如果相同不能修改
        if (oldPassword.equals(newPassword)) {
            log.warn("要修改的密码和原密码相同");
            throw new ApplicationException("要修改的密码和原密码相同");
        }
        // 生成新的盐值
        String newSalt = UUIDUtil.UUID_32();
        // 根据盐值和新密码进行加密
        String newMd5Password = Md5Util.md5Salt(newPassword,newSalt);
        // 写入数据库
        User updateUser = new User();
        updateUser.setId(id);
        updateUser.setPassword(newMd5Password);
        updateUser.setSalt(newSalt);
        updateUser.setUpdateTime(new Date());
        // 调用dao层
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        if (row != 1) {
            log.warn(ResultCode.ERROR_SERVICES.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
        // 更改成功
    }

    @Override
    public void editAvatarUrl(User user, MultipartFile file) {
//        user.setAvatarUrl(downloadUrl);
//        int row = userMapper.updateByPrimaryKey(user);
//        if (row != 1) {
//            log.error("头像存入MySQL数据库失败...");
//            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
//        }
        // 上传到OSS
        fileService.uploadFile(file,user);
    }

}
